package com.atguigu.gulimall.order.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.exception.BizCodeEnume;
import com.atguigu.common.exception.BizException;
import com.atguigu.common.utils.R;
import com.atguigu.common.vo.MemberResponseVo;
import com.atguigu.gulimall.order.Feign.*;
import com.atguigu.gulimall.order.constant.OrderConstant;
import com.atguigu.gulimall.order.entity.OrderItemEntity;
import com.atguigu.gulimall.order.enume.OrderStatusEnum;
import com.atguigu.gulimall.order.interceptor.Myinterceptor;
import com.atguigu.gulimall.order.to.OrderTo;
import com.atguigu.gulimall.order.vo.*;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.sun.corba.se.impl.resolver.ORBDefaultInitRefResolverImpl;
import com.sun.xml.internal.ws.util.CompletedFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.order.dao.OrderDao;
import com.atguigu.gulimall.order.entity.OrderEntity;
import com.atguigu.gulimall.order.service.OrderService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    private ThreadLocal<CreateOrderVo> confirmVoThreadLocal = new ThreadLocal<>();
    @Autowired
    MemberFeignService memberFeignService;
    @Autowired
    private ThreadPoolExecutor executor;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private WareFeignService wareFeignService;
    @Autowired
    private CartFeignService cartFeignService;
    @Autowired
    private ProductFeignService productFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
        OrderConfirmVo orderConfirmVo = new OrderConfirmVo();
        ThreadLocal<MemberResponseVo> loginUser = Myinterceptor.loginUser;
        MemberResponseVo memberResponseVo = loginUser.get();
        Thread thread = Thread.currentThread();
        System.out.println(thread.getId() + "主线程");
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        //远程查询所有的收货列表
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            Thread thread1 = Thread.currentThread();
            System.out.println(thread1.getId() + "线程1");
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());
            orderConfirmVo.setMemberAddressVos(address);
        }, executor);
        //远程查询所有的购物项
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            Thread thread2 = Thread.currentThread();
            System.out.println(thread2.getId() + "线程2");
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<OrderItemVo> cartItemChecked = cartFeignService.getCartItemChecked();
            orderConfirmVo.setOrderItemVos(cartItemChecked);
        }, executor);
        CompletableFuture.allOf(future, future1).get();
        Thread thread3 = Thread.currentThread();
        System.out.println(thread3 + "完成了");
        //获取用户的积分信息
        Integer integration = loginUser.get().getIntegration();
        orderConfirmVo.setIntegration(integration);
        //其他的数据自动计算
        return orderConfirmVo;
        //防重令牌 TODO
    }

    @Transactional
    @Override
    public OrderTo createOrder(CreateOrderVo createOrderVo) {
        // 防止用户重复提交 ,   使用token , 配合redis 的 lua 脚本使用, 防止 用户的重复提交
        String orderToken = createOrderVo.getOrderToken();
        MemberResponseVo memberResponseVo = Myinterceptor.loginUser.get();
        confirmVoThreadLocal.set(createOrderVo);
        String key = OrderConstant.ORDER_TOKEN + memberResponseVo.getId();
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Long execute = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), Arrays.asList(key), orderToken);
        if (execute == 0) {
            //对比失败,
            throw new BizException(160001, "订单创建失败");
        } else {
            OrderTo order = createOrder();
            BigDecimal payAmount = order.getOrder().getPayAmount();
            BigDecimal payPrice = createOrderVo.getPayPrice();
           if( Math.abs(payAmount.subtract(payPrice).doubleValue())<0.01){
               //对比成功
               //保存订单 和 订单项
               this.save(order.getOrder());
               //锁定库存
               WareSkuLockVo wareSkuLockVo = new WareSkuLockVo();
               wareSkuLockVo.setOrderSn(order.getOrder().getOrderSn());
               List<OrderItemVo> orderItemVos = order.getOrderItemEntity().stream().map(item -> {
                   OrderItemVo orderItemVo = new OrderItemVo();

                   orderItemVo.setCount(item.getSkuQuantity());
                   orderItemVo.setSkuid(item.getSkuId());
                   orderItemVo.setTitle(item.getSkuName());
                   return orderItemVo;
               }).collect(Collectors.toList());
               wareSkuLockVo.setLocks(orderItemVos);
               R r = wareFeignService.orderLockStock(wareSkuLockVo);
               if(r.getCode()==0){
                   //锁定成功
                   order.setCode(0);
                   return order;
               }else{
                   //锁定失败
                   order.setCode(3);
                    return order;
               }

           }else{
               //对比失败
               order.setCode(2);
               return order;
           }
        }
    }

    /**
     * 获取运费的通用方法
     *
     * @param id
     * @return
     */
    @Override
    public BigDecimal getcharge(Long id) {
        R charge = memberFeignService.getCharge(id);
        MemberAddressVo memberAddressVo = charge.getData("memberReceiveAddress", new TypeReference<MemberAddressVo>() {
        });
        return getCountCharge(memberAddressVo);
    }

    /**
     * 计算运费方法
     *
     * @param memberAddressVo
     * @return
     */
    private BigDecimal getCountCharge(MemberAddressVo memberAddressVo) {
        //暂时不做运费的计算  todo
        String phone = memberAddressVo.getPhone();
        String chargePay = phone.substring(phone.length() - 1, phone.length());
        return new BigDecimal(chargePay);
    }


    /**
     * 创建订单
     */
    public OrderTo createOrder() {
        OrderTo orderTo = new OrderTo();
        List<CartItemVo> cartItemVos = cartFeignService.getCartItemByMemberId();
        //创建订单
        OrderEntity orderEntity = buildOrder(cartItemVos);

        //创建订单项
        List<OrderItemEntity> orderItemEntities = buildOrderItems(cartItemVos, orderEntity.getOrderSn());
        orderTo.setOrder(orderEntity);
        orderTo.setOrderItemEntity(orderItemEntities);
        return  orderTo ;
    }

    /**
     * 构建订单
     *
     * @return
     */
    public OrderEntity buildOrder(List<CartItemVo> cartItemVos) {
        MemberResponseVo memberResponseVo = Myinterceptor.loginUser.get();

        CreateOrderVo createOrderVo = confirmVoThreadLocal.get();
        // 1. 创建订单
        //收货人信息
        R charge = memberFeignService.getCharge(createOrderVo.getAddressId());
        MemberAddressVo addressVo =charge.getData("memberReceiveAddress",new TypeReference<MemberAddressVo>() {
        });
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setMemberId(memberResponseVo.getId());
        String timeId = IdWorker.getTimeId();
        orderEntity.setOrderSn(timeId);
        //优惠券信息 , 暂时不做
        orderEntity.setCouponId(1L);
        orderEntity.setMemberUsername(memberResponseVo.getUsername());
        //计算总金额
        BigDecimal totalPrice = new BigDecimal(0);
        for (CartItemVo cartItemVo : cartItemVos) {
            totalPrice = cartItemVo.getTotalPrice();
        }
        orderEntity.setTotalAmount(totalPrice);
        //运费
        BigDecimal freightAmount = memberFeignService.getFreightAmount(createOrderVo.getAddressId());
        orderEntity.setFreightAmount(freightAmount);
        //优惠金额 , 暂无
        orderEntity.setPromotionAmount(new BigDecimal(0));
        // 积分信息  , 暂无
        orderEntity.setIntegrationAmount(new BigDecimal(0));
        // 优惠券, 暂无
        orderEntity.setCouponAmount(new BigDecimal(0));
        // 后台调整金额, 暂无
        orderEntity.setDiscountAmount(new BigDecimal(0));
        //支付方式
        orderEntity.setPayType(createOrderVo.getPayType());
        //订单来源, 暂无
        orderEntity.setSourceType(0);
        //订单状态
        orderEntity.setStatus(OrderStatusEnum.CREATE_NEW.getCode());
        //物流, 等待发货后设置
        //自动确认时间
        orderEntity.setAutoConfirmDay(7);
        //获得的积分
        orderEntity.setGrowth(0);
        //成长值
        orderEntity.setGrowth(0);
        //发票类型  无
        //应付总额
        BigDecimal payAmount = totalPrice.add(freightAmount);
        orderEntity.setPayAmount(payAmount);
        //设置收货人信息
        orderEntity.setReceiverPhone(addressVo.getPhone());
        orderEntity.setReceiverName(addressVo.getName());
        orderEntity.setReceiverPostCode(addressVo.getPostCode());
        orderEntity.setReceiverProvince(addressVo.getProvince());
        orderEntity.setReceiverCity(addressVo.getCity());
        orderEntity.setReceiverRegion(addressVo.getRegion());
        orderEntity.setReceiverDetailAddress(addressVo.getDetailAddress());
        orderEntity.setNote(createOrderVo.getNote());
        orderEntity.setDeleteStatus(0);
        orderEntity.setUseIntegration(0);
        return orderEntity;
    }

    /**
     * 构想订单项数据
     *
     * @param
     */
    private List<OrderItemEntity> buildOrderItems(List<CartItemVo> cartItemVos, String orderSn) {
        List<OrderItemEntity> orderItemEntities = cartItemVos.stream().map(item -> {
            OrderItemEntity orderItemEntity = buildOrderItem(item);
            orderItemEntity.setOrderSn(orderSn);
            return orderItemEntity;
        }).collect(Collectors.toList());
        return orderItemEntities;
    }

    private OrderItemEntity buildOrderItem(CartItemVo cartItemVo) {
        OrderItemEntity orderItemEntity = new OrderItemEntity();
        //1.订单信息

        //2. 商品的spu信息
        Long skuid = cartItemVo.getSkuid();
        SpuInfoVo spuInfoVo = productFeignService.getSpuInfoBySkuId(skuid).getData("spuInfoEntiy",new TypeReference<SpuInfoVo>() {
        });
        orderItemEntity.setSpuId(spuInfoVo.getId());
        orderItemEntity.setSpuName(spuInfoVo.getSpuName());
        orderItemEntity.setSpuBrand(spuInfoVo.getBrandId().toString());
        orderItemEntity.setCategoryId(spuInfoVo.getCatalogId());
        //3,商品的sku信息
        orderItemEntity.setSkuId(cartItemVo.getSkuid());
        orderItemEntity.setSkuName(cartItemVo.getTitle());
        List<String> skuAttrs = cartItemVo.getSkuAttr();
        String s = StringUtils.collectionToDelimitedString(skuAttrs, ";");
        orderItemEntity.setSkuAttrsVals(s);
        orderItemEntity.setSkuPrice(cartItemVo.getPrice());
        orderItemEntity.setSkuPic(cartItemVo.getImage());
        orderItemEntity.setSkuQuantity(cartItemVo.getCount());
        //4.优惠信息
        //5.积分信息
        orderItemEntity.setGiftGrowth(cartItemVo.getPrice().intValue());
        orderItemEntity.setGiftIntegration(cartItemVo.getPrice().intValue());

        //6. 订单项的价格信息
        orderItemEntity.setPromotionAmount(new BigDecimal(0));
        orderItemEntity.setCouponAmount(new BigDecimal(0));
        orderItemEntity.setIntegrationAmount(new BigDecimal(0));
        orderItemEntity.setRealAmount(cartItemVo.getTotalPrice());
        return orderItemEntity;
    }
}